#include<iostream>
#include<string.h>
using namespace std;

/*
C++ 函数模板：
    模板的意义：对类型也可以进行参数了
*/

template<typename T> //定义一个模板参数列表
bool compare(T a,T b) //compare是一个函数模板
{
    cout << "template compare" << endl;
    return a > b;
}

template <> // 针对compare函数模板，提供const char*类型的特例化版本
bool compare<const char *>(const char *a, const char *b) // bool compare(const char* a, const char* b)
{
    cout << "template compare<const char*>" << endl;
    return strcmp(a,b)>0;
}

//非模板函数，如果不显示调用函数模板的话，那么就会直接调用普通函数优先
bool compare(const char *a, const char *b)
{
    cout << "normal compare<const char*>" << endl;
    return strcmp(a, b) > 0;
}

// 函数模板中的非类型参数（整数，地址，指针）都是常量，只能使用不能修改
template<typename T,int SIZE>//模板后面要是传入的类型参数，那么就要传入const类型的
void sort(T* arr) //数组参数一般都是首地址传入，也就是指针
{
    for (int i = 0; i < SIZE - 1;i++)
    {
        for (int j = 0; j < SIZE - 1 - i;j++)
        {
            if(arr[j]>arr[j+1])
            {
                T temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

int main()
{
    compare<int>(10, 20);//函数调用点，编译器会自动从原模版实例化一个函数 bool compare(int a,int b)
    compare<double>(10.0, 20.0);//所以编译器要做的工作不会减少，因为它都会在编译过程中生成

    compare(10, 20); // 模板的实参推演，根据用户传入的类型自动推导模板类型参数的具体信息
    // compare<int>(10, 20);这个在之前执行过的话，那么这次模板的实参推演就不会再生成了
    //bool compare(int a,int b)，否则就形成了重定义

    // compare(10, 20.0);//无法自动推导成功，无法实现模板的实参推演

    // 对于某些类型，使用默认函数模板无法正确实现，所以就需要使用函数模板特例化
    compare("aaa", "bbb");//默认调用普通函数，而不是模板函数

    compare<const char *>("aaa", "bbb");//则调用模板的实例化函数

    int arr[] = {2, 3, 5, 7, 1, 2, 4, 8};
    const int size = sizeof(arr) / sizeof(arr[0]);
    sort<int, size>(arr);
    for(auto i:arr)
    {
        cout << i << " ";
    }

    return 0;
}